
#include "../include/Threadpool.h" 

#include <unistd.h>

namespace wd
{

Threadpool::Threadpool(size_t threadNum, size_t queSize)
: _threadNum(threadNum)
, _taskque(queSize)
, _isExit(false)
{
    //提前开辟好空间
    _threads.reserve(_threadNum);
}

Threadpool::~Threadpool()
{
    if(!_isExit) {
        stop();
    }
}

void Threadpool::start()
{
    for(size_t i = 0; i < _threadNum; ++i) {
        unique_ptr<Thread> up(new Thread(
            std::bind(&Threadpool::doTask, this)));
        //unique_ptr<Thread> up(new Thread([=](){
        //    doTask();
        //}));
        //std::move需要显式将一个左值转换为右值
        _threads.push_back(std::move(up));
    }

    for(auto & thread : _threads) {
        thread->start();
    }
}

//停止线程池，就是要回收每一个子线程
void Threadpool::stop()
{
    printf("Threadpool::stop()\n");
    //当任务队列中还有任务没有执行完毕时，就先等一等
    while(!_taskque.empty()) {
        sleep(2);
    }

    //bug:当每一个子线程都执行完了任务，由于速度过快，
    //stop函数所在的线程还没来得及将_isExit设置为true
    //每一个子线程就又进入下一次循环，阻塞在了pop方法之上
    _isExit = true;
    _taskque.wakeup();

    //回收每一个子线程
    for(auto & thread : _threads) {
        thread->join();
    }
}

//addTask方法充当的是生产者的角色
void Threadpool::addTask(Task task)
{
    if(task) {
        _taskque.push(task);
    }
}


//每一个子线程要做的事儿
void Threadpool::doTask()
{
    //不断地从任务队列中取任务
    while(!_isExit) {
        Task task = _taskque.pop();
        if(task) {
            task();
        }
    }
}

}//end of namespace wd
